package com.pubinfo.passbook.engine.cell.logic;

import com.pubinfo.passbook.common.exception.ServiceException;
import com.pubinfo.passbook.engine.cell.ComputeUnit;
import com.pubinfo.passbook.engine.chain.ComputeChain;
import com.pubinfo.passbook.engine.constants.ComputeUnitType;
import com.pubinfo.passbook.engine.utils.TextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * 逻辑类型计算单元
 *
 * @author zhouch
 * @date 2021/12/13 9:54
 */
@Slf4j
public abstract class ComputeLogicUnit<T, R> extends ComputeUnit<T, R> {

    protected ComputeChain<T, R> successComputeChain;
    protected ComputeChain<T, R> failedComputeChain;

    public abstract Boolean then(T data, R result);

    @Override
    public R compute(T data, R beforeVal) {

        // 设置2条计算链的缓存
        successComputeChain.setCache(cache);
        failedComputeChain.setCache(cache);

        R result;

        log.info("{}: 执行条件分支链...", getClass().getSimpleName());

        boolean condition = then(data, beforeVal);

        if (condition) {
            result = successComputeChain.compute(data, beforeVal);
        } else {
            result = failedComputeChain.compute(data, beforeVal);
        }

        log.info("{}: 条件分支执行完成.", getClass().getSimpleName());

        outputComputeMessage(condition);
        return result;
    }

    @Override
    public String getUnitType() {
        return ComputeUnitType.LOGIC;
    }

    /**
     * 逻辑单元需要2条额外的计算链
     *
     * @return
     */
    public void setSuccessComputeChain(ComputeChain<T, R> chain) {
        successComputeChain = chain;
    }

    public void setFailedComputeChain(ComputeChain<T, R> chain) {
        failedComputeChain = chain;
    }


    @Override
    public String getResultType() {
        String successChainResultType = successComputeChain.getResultType();
        String failedChainResultType = failedComputeChain.getResultType();

        if (successChainResultType.contentEquals(failedChainResultType)) {
            return successChainResultType;
        } else {
            throw new ServiceException("逻辑计算单元的分支计算结果类型不相同: successChainResultType: " + successChainResultType + " " + "failedChainResultType: " + failedChainResultType);
        }
    }

    /**
     * 如果实现了getName 那么Logic类型的计算单元会自动将执行信息压入缓存
     *
     * @param condition
     */
    protected void outputComputeMessage(boolean condition) {
        if (StringUtils.isNotBlank(getName())) {
            outputComputeMessage(TextUtils.boolToChinese(condition));
        }
    }

    /**
     * 手动实现执行信息压入缓存, 该函数需要在compute中调用
     *
     * @param name
     * @param condition
     */
    protected void outputComputeMessage(String name, boolean condition) {
        outputComputeMessage(name, TextUtils.boolToChinese(condition));
    }
}
